package com.zrrd.yt.product.service.serviceImpl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zrrd.yt.model.product.*;
import com.zrrd.yt.product.mapper.*;
import com.zrrd.yt.product.service.SkuInfoService;
import com.zrrd.yt.service.cache.GmallCache;
import com.zrrd.yt.service.constant.RedisConst;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author HongyueYang
 */
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Autowired
    private SpuImageMapper spuImageMapper;
    @Autowired
    private SpuSaleAttrMapper spuSaleAttrMapper;
    @Autowired
    private SkuImageMapper skuImageMapper;
    @Autowired
    private SkuAttrValueMapper skuAttrValueMapper;
    @Autowired
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;
    @Autowired
    private BaseCategoryViewMapper baseCategoryViewMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    //根据spu的id获取spu图片列表
    @Override
    public List<SpuImage> getSpuImageList(Long spuId) {
        QueryWrapper<SpuImage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("spu_id", spuId);
        return spuImageMapper.selectList(queryWrapper);
    }

    //根据spu的id获取spu的销售属性
    @Override
    public List<SpuSaleAttr> getSpuSaleAttrList(Long spuId) {
        return spuSaleAttrMapper.selectSpuSaleAttrList(spuId);
    }

    //保存sku信息
    @Override
    @Transactional
    public void saveSkuInfo(SkuInfo skuInfo) {
        //1.保存sku信息--->spu_info
        this.save(skuInfo);
        //2.保存sku图片信息--->spu_image
        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        if (skuImageList != null && skuImageList.size() > 0) {
            for (SkuImage skuImage : skuImageList) {
                skuImage.setSkuId(skuInfo.getId());
                skuImageMapper.insert(skuImage);
            }
        }
        //3.保存sku平台属性值信息--->sku_attr_value(记录的是关键数据)
        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
        if (skuAttrValueList != null && skuAttrValueList.size() > 0) {
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(skuInfo.getId());
                skuAttrValueMapper.insert(skuAttrValue);
            }
        }
        //4.保存sku销售属性值信息--->sku_sale_attr_value(记录的是关系数据)
        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
        if (skuSaleAttrValueList != null && skuSaleAttrValueList.size() > 0) {
            for (SkuSaleAttrValue skuSaleAttrValue : skuSaleAttrValueList) {
                skuSaleAttrValue.setSkuId(skuInfo.getId());
                skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
                skuSaleAttrValueMapper.insert(skuSaleAttrValue);
            }
        }

    }

    @Override
    @GmallCache(prefix = RedisConst.SKUKEY_PREFIX)
    public SkuInfo getSkuInfo(Long skuId) throws InterruptedException {
        //防止缓存数据的redis泵机，直接返回数据库数据
        return this.getSkuInfoByDB(skuId);

    }


    //从数据库中查询数据
    public SkuInfo getSkuInfoByDB(Long skuId) {
        //根据skuID查询sku信息
        SkuInfo skuInfo = this.getById(skuId);
        //根据skuID查询sku图片信息
        QueryWrapper<SkuImage> wrapper = new QueryWrapper<>();
        wrapper.eq("sku_id", skuId);
        List<SkuImage> skuImageList = skuImageMapper.selectList(wrapper);
        //给skuInfo对象设置图片
        skuInfo.setSkuImageList(skuImageList);
        return skuInfo;
    }

    //根据三级分类ID 查询出3个分类的视图
    @Override
    @GmallCache(prefix = "categoryView:")
    public BaseCategoryView getCategoryView(Long category3Id) {
        return baseCategoryViewMapper.selectById(category3Id);
    }

    @Override
    public BigDecimal getSkuPrice(Long skuId) {
        SkuInfo skuInfo = this.getById(skuId);
        if (skuInfo != null) {
            return skuInfo.getPrice();
        }
        return new BigDecimal(0);
    }

    @Override
    @GmallCache(prefix = "SpuSaleAttr:")
    public List<SpuSaleAttr> selectSpuSaleAttrListBySku(Long spuId, Long skuId) {
        return spuSaleAttrMapper.selectSpuSaleAttrListBySku(spuId, skuId);
    }

    @Override
    @GmallCache(prefix = "valuesJson:")
    public Map selectSkuAttrValueBySpu(Long spuId) {
        //调用mapper方法
        List<Map> list = skuSaleAttrValueMapper.selectSkuAttrValueBySpu(spuId);
        //创建最终返回的Map集合
        Map<Object, Object> map = new HashMap<>();
        //遍历list
        for (Map m : list) {
            map.put(m.get("value_ids"), m.get("sku_id"));
        }
        return map;
    }

    @Override
    @GmallCache(prefix = "categoryList:")
    public List<JSONObject> getBaseCategoryListJson() {
        //创建最终返回的JSON对象集合
        List<JSONObject> list = new ArrayList<>();
        //获取所有分类的数据 返回的是视图的数据 每条数据包括123级分类
        List<BaseCategoryView> baseCategoryViewList = baseCategoryViewMapper.selectList(null);

        //将获取到的分类信息使用stream流进行拆分以及分组操作，根据一级分类id进行分组
        Map<Long, List<BaseCategoryView>> category1Map = baseCategoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));
        //定义变量
        int index = 1;
        //获取一级分类的所有数据
        for (Map.Entry<Long, List<BaseCategoryView>> entry1 : category1Map.entrySet()) {
            //获取一级分类id（key）
            Long category1Id = entry1.getKey();
            //获取一级分类的所有数据（包含2，3级）
            List<BaseCategoryView> category2List = entry1.getValue();
            //创建一级分类的JSON对象
            JSONObject category1 = new JSONObject();
            //给对象设置属性
            category1.put("index", index);
            category1.put("categoryId", category1Id);
            category1.put("categoryName", category2List.get(0).getCategory1Name());
            //index变量++
            index++;


            //根据二级分类id进行分组
            Map<Long, List<BaseCategoryView>> category2Map = category2List.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
           //创建装载二级分类的JSON对象集合
            List<JSONObject> category2Child = new ArrayList<>();
            //获取二级分类的所有数据
            for (Map.Entry<Long, List<BaseCategoryView>> entry2 : category2Map.entrySet()) {
                //获取二级分类id
                Long category2Id = entry2.getKey();
                //获取二级分类的所有数据（包含3级）
                List<BaseCategoryView> category3List = entry2.getValue();
                //创建二级分类的JSON对象
                JSONObject category2 = new JSONObject();
                //给对象设置属性
                category2.put("categoryId", category2Id);
                category2.put("categoryName", category3List.get(0).getCategory2Name());
                //将二级分类对象装进二级分类集合
                category2Child.add(category2);


                //创建一个装载三级分类的JSON对象集合
                List<JSONObject> category3Child = new ArrayList<>();
                //遍历三级分类数据
                for (BaseCategoryView baseCategoryView : category2List) {
                    //创建三级分类JSON对象
                    JSONObject category3 = new JSONObject();
                    //给对象设置属性
                    category3.put("categoryId", baseCategoryView.getCategory3Id());
                    category3.put("categoryName", baseCategoryView.getCategory3Name());
                    //将三级分类对象装进三级分类集合
                    category3Child.add(category3);
                }
                //将三级分类集合设置给二级分类对象
                category2.put("categoryChild", category3Child);
            }
            //将二级分类集合设置给一级分类对象
            category1.put("categoryChild", category2Child);
            //将一级对象添加进集合
            list.add(category1);
        }
        return list;
    }
}
